Setting up the data so that the difference between the SNAP data and
the airport specific data.
Step 1: Extract the RCP Site data from the SNAP 5 model averages.
Step 2: Import both data sets
Step 3: Set up the Z-score calculation based on notes from meeting
with Alan Hamlet
Step 4: Calculate the average and standard deviation of the daily
differences
Step 5 (not in this file): rerun models with the new forecast
temperatures – List these files here after the fact to make sure this is
up to date
Load in the packages needed
library(dplyr)
Setting up the workspace
library(dplyr)
library(ggplot2)
setwd("~/Library/CloudStorage/Dropbox/SWEL/CopperRiverDelta/PondTemps/DataAnalysis/PondTempsAnalysis")
Copper River RCP 4.5
Read in the data
# Read data files
CR_45 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR45.csv")
CRD_airport <- read.csv(file = "BiasCorrection/CR_PondAirTemp_mean.csv")
CRD_airport <- CRD_airport %>% select(-X) # Remove unnecessary column 'X'
Check dates
# Fix 'date' in CR_45 to ensure it's in Date format
CR_45$date <- as.Date(paste("01", CR_45$date), format = "%d %b %Y")
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(CR_45$date)) # Check if there are any missing values (should be 0)
[1] 0
Trim dates
# Trim CR_45 to the date range of CRD_airport
start_date <- min(CRD_airport$Date)
end_date <- max(CRD_airport$Date)
# Subset CR_45 to match the date range of CRD_airport
CR_45_trimmed <- CR_45 %>%
filter(date >= start_date & date <= end_date)
Plot pre-correction data
library(ggplot2)
# Ensure 'Date' in CRD_airport is in Date format
CRD_airport$Date <- as.Date(CRD_airport$Date)
# Check structure of CR_45_trimmed to confirm correct Date column
str(CR_45_trimmed)
'data.frame': 96 obs. of 4 variables:
$ date : Date, format: "2012-01-01" "2012-02-01" "2012-03-01" ...
$ avg_temperature: num -6.66 -3.84 -0.02 3.28 7.2 ...
$ std_temperature: num 1.483 5.188 2.846 0.944 0.728 ...
$ precision : num 0.455 0.0371 0.1235 1.1211 1.8868 ...
# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = CR_45_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Uncorrected Predicted Temperatures - CRD RCP 4.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_CR45.jpeg", plot = Plot, width = 8, height = 6)

z-score bias correction
# Calculate mean and standard deviation for observed and predicted temperatures
mu_obs <- mean(CRD_airport$Air_MonthAvg, na.rm = TRUE)
sigma_obs <- sd(CRD_airport$Air_MonthAvg, na.rm = TRUE)
mu_pred <- mean(CR_45_trimmed$avg_temperature, na.rm = TRUE)
sigma_pred <- sd(CR_45_trimmed$avg_temperature, na.rm = TRUE)
Correction applied to the 2012-2020 dataset
# Apply the z-score bias correction to the predicted data
CR_45_trimmed$corrected_temp <- (CR_45_trimmed$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(CR_45_trimmed)
NA
Plot corrected and observed values
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = CR_45_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Corrected Predicted Temperatures - CRD RCP 4.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12, face = "italic"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_CR45.jpeg", plot = Plot, width = 8, height = 6)

Plotting the values here
# Plot Original vs Corrected Predicted Temperatures (No Observed Values)
Plot <- ggplot() +
# Plot the original predicted temperatures (uncorrected)
geom_line(data = CR_45_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2, linetype = "solid") +
# Plot the corrected predicted temperatures
geom_line(data = CR_45_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
# Set plot labels
labs(
title = "Original vs Corrected Predicted Temperatures - CRD RCP 4.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
# Customize x-axis to show months/years clearly
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
# Define custom colors for the plot
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
# Minimal theme for the plot
theme_minimal() +
# Customizations for appearance
theme(
axis.text.x = element_text(angle = 45, hjust = 1), # Rotate x-axis labels for clarity
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectedComparison_CR45.jpeg", plot = Plot, width = 8, height = 6)

Correction applied to the whole dataset
# Apply the z-score bias correction to the predicted data
CR_45$corrected_temp <- (CR_45$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(CR_45)
Plot this to make it into the same predicted (corrected) + predicted
(uncorrected) with the error included
# Plot Original vs Corrected Predicted Temperatures (No Observed Values)
Plot <- ggplot() +
# Plot the original predicted temperatures (uncorrected)
geom_line(data = CR_45, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2, linetype = "solid") +
# Plot the corrected predicted temperatures
geom_line(data = CR_45, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
# Set plot labels
labs(
title = "Original vs Corrected Predicted Temperatures - CRD RCP 4.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
# Customize x-axis to show months/years clearly
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
# Define custom colors for the plot
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
# Minimal theme for the plot
theme_minimal() +
# Customizations for appearance
theme(
axis.text.x = element_text(angle = 45, hjust = 1), # Rotate x-axis labels for clarity
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_CR45.jpeg", plot = Plot, width = 8, height = 6)

Save the new file
# Save the updated dataset with the corrected temperatures to a new CSV file
write.csv(CR_45, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR45_corrected.csv", row.names = FALSE)
Copper River RCP 8.5
Read in the data
# Read data files
CR_85 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR85.csv")
CRD_airport <- read.csv(file = "BiasCorrection/CR_PondAirTemp_mean.csv")
CRD_airport <- CRD_airport %>% select(-X) # Remove unnecessary column 'X'
Check dates
# Fix 'date' in CR_85 to ensure it's in Date format
CR_85$date <- as.Date(paste("01", CR_85$date), format = "%d %b %Y")
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(CR_85$date)) # Check if there are any missing values (should be 0)
[1] 0
Trim dates
# Trim CR_85 to the date range of CRD_airport
start_date <- min(CRD_airport$Date)
end_date <- max(CRD_airport$Date)
# Subset CR_85 to match the date range of CRD_airport
CR_85_trimmed <- CR_85 %>%
filter(date >= start_date & date <= end_date)
Plot pre-correction data
library(ggplot2)
# Ensure 'Date' in CRD_airport is in Date format
CRD_airport$Date <- as.Date(CRD_airport$Date)
# Check structure of CR_85_trimmed to confirm correct Date column
str(CR_85_trimmed)
'data.frame': 96 obs. of 4 variables:
$ date : Date, format: "2012-01-01" "2012-02-01" "2012-03-01" ...
$ avg_temperature: num -6.54 -4.5 -1.92 3.24 6.64 ...
$ std_temperature: num 4.46 4.2 3.89 1.23 1.12 ...
$ precision : num 0.0503 0.0568 0.0662 0.6631 0.7981 ...
# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = CR_85_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Uncorrected Predicted Temperatures - CRD RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 85, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_CR85.jpeg", plot = Plot, width = 8, height = 6)

z-score bias correction
# Calculate mean and standard deviation for observed and predicted temperatures
mu_obs <- mean(CRD_airport$Air_MonthAvg, na.rm = TRUE)
sigma_obs <- sd(CRD_airport$Air_MonthAvg, na.rm = TRUE)
mu_pred <- mean(CR_85_trimmed$avg_temperature, na.rm = TRUE)
sigma_pred <- sd(CR_85_trimmed$avg_temperature, na.rm = TRUE)
Correction applied to the 2012-2020 dataset
# Apply the z-score bias correction to the predicted data
CR_85_trimmed$corrected_temp <- (CR_85_trimmed$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(CR_85_trimmed)
NA
Plot corrected and observed values
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = CR_85_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Corrected Predicted Temperatures - CRD RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 85, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12, face = "italic"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_CR85.jpeg", plot = Plot, width = 8, height = 6)

Plotting the values here
# Plot Original vs Corrected Predicted Temperatures (No Observed Values)
Plot <- ggplot() +
# Plot the original predicted temperatures (uncorrected)
geom_line(data = CR_85_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2, linetype = "solid") +
# Plot the corrected predicted temperatures
geom_line(data = CR_85_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
# Set plot labels
labs(
title = "Original vs Corrected Predicted Temperatures - CRD RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
# Customize x-axis to show months/years clearly
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
# Define custom colors for the plot
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
# Minimal theme for the plot
theme_minimal() +
# Customizations for appearance
theme(
axis.text.x = element_text(angle = 85, hjust = 1), # Rotate x-axis labels for clarity
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectedComparison_CR85.jpeg", plot = Plot, width = 8, height = 6)

Correction applied to the whole dataset
# Apply the z-score bias correction to the predicted data
CR_85$corrected_temp <- (CR_85$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(CR_85)
Plot this to make it into the same predicted (corrected) + predicted
(uncorrected) with the error included
# Plot Original vs Corrected Predicted Temperatures (No Observed Values)
Plot <- ggplot() +
# Plot the original predicted temperatures (uncorrected)
geom_line(data = CR_85, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2, linetype = "solid") +
# Plot the corrected predicted temperatures
geom_line(data = CR_85, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = CRD_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
# Set plot labels
labs(
title = "Original vs Corrected Predicted Temperatures - CRD RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
# Customize x-axis to show months/years clearly
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
# Define custom colors for the plot
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
# Minimal theme for the plot
theme_minimal() +
# Customizations for appearance
theme(
axis.text.x = element_text(angle = 85, hjust = 1), # Rotate x-axis labels for clarity
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_CR85.jpeg", plot = Plot, width = 8, height = 6)

Save the new file
# Save the updated dataset with the corrected temperatures to a new CSV file
write.csv(CR_85, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_CR85_corrected.csv", row.names = FALSE)
Yakutat Foreland RCP 4.5
Read in the data
# Read data files
YF_45 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF45.csv")
YF_airport <- read.csv(file = "BiasCorrection/YF_PondAirTemp_mean.csv")
YF_airport <- YF_airport %>% select(-X) # Remove unnecessary column 'X'
Check dates
# Fix 'date' in YF_45 to ensure it's in Date format
YF_45$date <- as.Date(paste("01", YF_45$date), format = "%d %b %Y")
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(YF_45$date)) # Check if there are any missing values (should be 0)
[1] 0
Trim dates
# Trim YF_45 to the date range of YF_airport
start_date <- min(YF_airport$Date)
end_date <- max(YF_airport$Date)
# Subset YF_45 to match the date range of YF_airport
YF_45_trimmed <- YF_45 %>%
filter(date >= start_date & date <= end_date)
Plot pre-correction data
library(ggplot2)
# Ensure 'Date' in YF_airport is in Date format
YF_airport$Date <- as.Date(YF_airport$Date)
# Check structure of YF_45_trimmed to confirm correct Date column
str(YF_45_trimmed)
'data.frame': 96 obs. of 4 variables:
$ date : Date, format: "2012-01-01" "2012-02-01" "2012-03-01" ...
$ avg_temperature: num -6.76 -3.42 0.04 3.58 7.46 ...
$ std_temperature: num 0.695 5.172 2.487 0.986 0.893 ...
$ precision : num 2.0704 0.0374 0.1617 1.0288 1.2531 ...
# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = YF_45_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Uncorrected Predicted Temperatures - YF 4.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_YF45.jpeg", plot = Plot, width = 8, height = 6)

z-score bias correction
# Calculate mean and standard deviation for observed and predicted temperatures
mu_obs <- mean(YF_airport$Air_MonthAvg, na.rm = TRUE)
sigma_obs <- sd(YF_airport$Air_MonthAvg, na.rm = TRUE)
mu_pred <- mean(YF_45_trimmed$avg_temperature, na.rm = TRUE)
sigma_pred <- sd(YF_45_trimmed$avg_temperature, na.rm = TRUE)
Correction applied to the 2012-2020 dataset
# Apply the z-score bias correction to the predicted data
YF_45_trimmed$corrected_temp <- (YF_45_trimmed$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(YF_45_trimmed)
NA
Plot corrected and observed values
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = YF_45_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Corrected Predicted Temperatures - YF RCP 4.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12, face = "italic"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_YF45.jpeg", plot = Plot, width = 8, height = 6)

Plotting the values here
<!-- rnb-source-end -->
<!-- rnb-output-begin eyJkYXRhIjoiRXJyb3I6IGF0dGVtcHQgdG8gdXNlIHplcm8tbGVuZ3RoIHZhcmlhYmxlIG5hbWVcbiJ9 -->
Error: attempt to use zero-length variable name
<!-- rnb-output-end -->
<!-- rnb-chunk-end -->
<!-- rnb-text-begin -->
Correction applied to the whole dataset
<!-- rnb-text-end -->
<!-- rnb-chunk-begin -->
<!-- rnb-frame-begin eyJtZXRhZGF0YSI6eyJjbGFzc2VzIjpbImRhdGEuZnJhbWUiXSwibnJvdyI6NiwibmNvbCI6NSwic3VtbWFyeSI6eyJEZXNjcmlwdGlvbiI6WyJkZiBbNiDDlyA1XSJdfX0sInJkZiI6Ikg0c0lBQUFBQUFBQUF3dHlpVERtaXVCaVlHQmdabUJoWVdSZ1pnVXlHVmhEUTl4MExSZ1lXSmlBSEVZR0ZnWk9FRjBCVkNRTWtnWFNmRUNhemVIc041QnFCb2R6ckEwUVdnVEtWNGJ5amFDMEV3TUVvQmpJbXB5VFdGd01aQWdnQ2JLNEpKYWtBdWwvUUF5MjVJQTBsMjNCNHV0Y0I3aGpOTDRlNm8reFgxTDEwSDJkU0xVREQxRFF0bUNKZyt4MXNBSUhUWkFxMjBLWVB2dG50bDZ2RCtmWk9vaHNpUDNYYit2cndQeWtlazVHMFU3Nzl6MzFPYXE3VGV6ZlRQMDl6L2pqS3dmR3YvWHM3YytkWWZvY0dDWm9wVjM2dE05K3NYSnJNLytiRlBzam16ZUdhcjJmWS8raDlPK1QyYS9lMlgvaHVjcHM2bkRhL3FUL2JuWEZWUnh3ZHdyRXhkLzEwZkxjLzRYbHcrU2c5UmIydndVM0hXVS9LdU1nZFA3d2JQRWZFZzRLalBOMWNnK29PbWg4aWZ5NnFNUU1QVER5RW5OVFlZSEJDZ3VNRkZCZ1FOajhpV1hwOFNXcHVRV3BSWWtscFVWdzRlS1NGQ3pDbkFWRnFjbVp4Wm41ZVZBQnZ1VDhJcUJRU1NwRU5acnRuRVg1NVhvd0YvQUNNVk1ESk1MWUlBcVovcU5GRXhmUVpZbDZhVVZBTFpESVFqR09QYitnQkdnMTBEQW1ZWWdoS0pvWmk5QUVCRXZ6UUphbjZDWm5sT1psNnhxWm02RXBZQzdJU3dmWkNoYUNZRjRvelliRVpvVzRneG5tV2phb2RyYlV2UFRNUEZqWXNPWWtKcVhtd0V4T1NTMkRCUkV3RU1CaG9GZFFsSmxYQXZNcFVMUllyeVMvSkJHbWhTczVQd2NtQWttby93QzYvU0JNUndNQUFBPT0ifQ== -->
<div data-pagedtable="false">
<script data-pagedtable-source type="application/json">
{"columns":[{"label":[""],"name":["_rn_"],"type":[""],"align":["left"]},{"label":["date"],"name":[1],"type":["date"],"align":["right"]},{"label":["avg_temperature"],"name":[2],"type":["dbl"],"align":["right"]},{"label":["std_temperature"],"name":[3],"type":["dbl"],"align":["right"]},{"label":["precision"],"name":[4],"type":["dbl"],"align":["right"]},{"label":["corrected_temp"],"name":[5],"type":["dbl"],"align":["right"]}],"data":[{"1":"2012-01-01","2":"-6.76","3":"0.6949820","4":"2.07039337","5":"-4.092163","_rn_":"1"},{"1":"2012-02-01","2":"-3.42","3":"5.1722336","4":"0.03738038","5":"-1.251206","_rn_":"2"},{"1":"2012-03-01","2":"0.04","3":"2.4865639","4":"0.16173379","5":"1.691821","_rn_":"3"},{"1":"2012-04-01","2":"3.58","3":"0.9859006","4":"1.02880658","5":"4.702895","_rn_":"4"},{"1":"2012-05-01","2":"7.46","3":"0.8933085","4":"1.25313283","5":"8.003168","_rn_":"5"},{"1":"2012-06-01","2":"12.72","3":"2.2487774","4":"0.19774570","5":"12.477249","_rn_":"6"}],"options":{"columns":{"min":{},"max":[10],"total":[5]},"rows":{"min":[10],"max":[10],"total":[6]},"pages":{}}}
</script>
</div>
<!-- rnb-frame-end -->
<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuIyBDaGVjayB0aGUgZmlyc3QgZmV3IHJvd3MgdG8gdmVyaWZ5XG5oZWFkKFlGXzQ1KVxuXG5cbmBgYCJ9 -->
```r
# Check the first few rows to verify
head(YF_45)
Plot this to make it into the same predicted (corrected) + predicted
(uncorrected) with the error included

Save the new file
# Save the updated dataset with the corrected temperatures to a new CSV file
write.csv(YF_45, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF45_corrected.csv", row.names = FALSE)
Yakutat Foreland RCP 8.5
Read in the data
# Read data files
YF_85 <- read.csv(file = "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF85.csv")
YF_airport <- read.csv(file = "BiasCorrection/YF_PondAirTemp_mean.csv")
YF_airport <- YF_airport %>% select(-X) # Remove unnecessary column 'X'
Check dates
# Fix 'date' in YF_85 to ensure it's in Date format
YF_85$date <- as.Date(paste("01", YF_85$date), format = "%d %b %Y")
# Ensure that there are no NAs in the 'date' column after conversion
sum(is.na(YF_85$date)) # Check if there are any missing values (should be 0)
[1] 0
Trim dates
# Trim YF_85 to the date range of YF_airport
start_date <- min(YF_airport$Date)
end_date <- max(YF_airport$Date)
# Subset YF_85 to match the date range of YF_airport
YF_85_trimmed <- YF_85 %>%
filter(date >= start_date & date <= end_date)
Plot pre-correction data
library(ggplot2)
# Ensure 'Date' in YF_airport is in Date format
YF_airport$Date <- as.Date(YF_airport$Date)
# Check structure of YF_85_trimmed to confirm correct Date column
str(YF_85_trimmed)
'data.frame': 96 obs. of 4 variables:
$ date : Date, format: "2012-01-01" "2012-02-01" "2012-03-01" ...
$ avg_temperature: num -5.88 -4.18 -1.46 3.66 6.7 ...
$ std_temperature: num 3.528 3.283 3.769 1.537 0.987 ...
$ precision : num 0.0803 0.0928 0.0704 0.4232 1.0256 ...
# Plot Observed vs Uncorrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = YF_85_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2) +
geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Uncorrected Predicted Temperatures - YF RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 85, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Pre-CorrectionComparison_YF85.jpeg", plot = Plot, width = 8, height = 6)

z-score bias correction
# Calculate mean and standard deviation for observed and predicted temperatures
mu_obs <- mean(YF_airport$Air_MonthAvg, na.rm = TRUE)
sigma_obs <- sd(YF_airport$Air_MonthAvg, na.rm = TRUE)
mu_pred <- mean(YF_85_trimmed$avg_temperature, na.rm = TRUE)
sigma_pred <- sd(YF_85_trimmed$avg_temperature, na.rm = TRUE)
Correction applied to the 2012-2020 dataset
# Apply the z-score bias correction to the predicted data
YF_85_trimmed$corrected_temp <- (YF_85_trimmed$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(YF_85_trimmed)
NA
Plot corrected and observed values
# Plotting Observed vs Corrected Predicted Temperatures
Plot <- ggplot() +
geom_line(data = YF_85_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
labs(
title = "Observed vs Corrected Predicted Temperatures - YF RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
scale_color_manual(values = c("Predicted (Corrected)" = "blue", "Observed" = "black")) +
theme_minimal() +
theme(
axis.text.x = element_text(angle = 85, hjust = 1),
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
plot.subtitle = element_text(size = 12, face = "italic"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/Corrected_YF85.jpeg", plot = Plot, width = 8, height = 6)

Plotting the values here
# Plot Original vs Corrected Predicted Temperatures (No Observed Values)
Plot <- ggplot() +
# Plot the original predicted temperatures (uncorrected)
geom_line(data = YF_85_trimmed, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2, linetype = "solid") +
# Plot the corrected predicted temperatures
geom_line(data = YF_85_trimmed, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
# Set plot labels
labs(
title = "Original vs Corrected Predicted Temperatures - YF RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
# Customize x-axis to show months/years clearly
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
# Define custom colors for the plot
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
# Minimal theme for the plot
theme_minimal() +
# Customizations for appearance
theme(
axis.text.x = element_text(angle = 85, hjust = 1), # Rotate x-axis labels for clarity
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/CorrectedComparison_YF85.jpeg", plot = Plot, width = 8, height = 6)

Correction applied to the whole dataset
# Apply the z-score bias correction to the predicted data
YF_85$corrected_temp <- (YF_85$avg_temperature - mu_pred) / sigma_pred * sigma_obs + mu_obs
# Check the first few rows to verify
head(YF_85)
Plot this to make it into the same predicted (corrected) + predicted
(uncorrected) with the error included
# Plot Original vs Corrected Predicted Temperatures (No Observed Values)
Plot <- ggplot() +
# Plot the original predicted temperatures (uncorrected)
geom_line(data = YF_85, aes(x = date, y = avg_temperature, color = "Predicted (Uncorrected)"), size = 1.2, linetype = "solid") +
# Plot the corrected predicted temperatures
geom_line(data = YF_85, aes(x = date, y = corrected_temp, color = "Predicted (Corrected)"), size = 1.2, linetype = "dashed") +
geom_line(data = YF_airport, aes(x = Date, y = Air_MonthAvg, color = "Observed"), size = 1.2) +
# Set plot labels
labs(
title = "Original vs Corrected Predicted Temperatures - YF RCP 8.5",
x = "Date",
y = "Temperature (°C)",
color = "Temperature Type"
) +
# Customize x-axis to show months/years clearly
scale_x_date(
date_labels = "%b %Y", # Format x-axis as Month-Year
date_breaks = "1 month", # Set breaks every month
expand = c(0, 0) # Remove extra space at the edges
) +
# Define custom colors for the plot
scale_color_manual(values = c("Predicted (Uncorrected)" = "red", "Predicted (Corrected)" = "blue")) +
# Minimal theme for the plot
theme_minimal() +
# Customizations for appearance
theme(
axis.text.x = element_text(angle = 85, hjust = 1), # Rotate x-axis labels for clarity
axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 14, face = "bold"),
legend.title = element_text(size = 12),
legend.text = element_text(size = 10)
)
Plot
ggsave("BiasCorrection/Geo_BiasCorrection/Plots/FullCorrection_YF85.jpeg", plot = Plot, width = 8, height = 6)

Save the new file
# Save the updated dataset with the corrected temperatures to a new CSV file
write.csv(YF_85, "BiasCorrection/Geo_BiasCorrection/DataFiles/SNAP_YF85_corrected.csv", row.names = FALSE)
LS0tCnRpdGxlOiAiU05BUCBEYXRhIEV4dHJhY3Rpb24gYW5kIEJpYXMgQ29ycmVjdGlvbiBGaWxlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpTZXR0aW5nIHVwIHRoZSBkYXRhIHNvIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgU05BUCBkYXRhIGFuZCB0aGUgYWlycG9ydCBzcGVjaWZpYyBkYXRhLgoKU3RlcCAxOiBFeHRyYWN0IHRoZSBSQ1AgU2l0ZSBkYXRhIGZyb20gdGhlIFNOQVAgNSBtb2RlbCBhdmVyYWdlcy4KClN0ZXAgMjogSW1wb3J0IGJvdGggZGF0YSBzZXRzCgpTdGVwIDM6IFNldCB1cCB0aGUgWi1zY29yZSBjYWxjdWxhdGlvbiBiYXNlZCBvbiBub3RlcyBmcm9tIG1lZXRpbmcgd2l0aCBBbGFuIEhhbWxldAoKU3RlcCA0OiBDYWxjdWxhdGUgdGhlIGF2ZXJhZ2UgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgZGFpbHkgZGlmZmVyZW5jZXMKClN0ZXAgNSAobm90IGluIHRoaXMgZmlsZSk6IHJlcnVuIG1vZGVscyB3aXRoIHRoZSBuZXcgZm9yZWNhc3QgdGVtcGVyYXR1cmVzIC0tIExpc3QgdGhlc2UgZmlsZXMgaGVyZSBhZnRlciB0aGUgZmFjdCB0byBtYWtlIHN1cmUgdGhpcyBpcyB1cCB0byBkYXRlCgpMb2FkIGluIHRoZSBwYWNrYWdlcyBuZWVkZWQKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpgYGAKClNldHRpbmcgdXAgdGhlIHdvcmtzcGFjZQoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCnNldHdkKCJ+L0xpYnJhcnkvQ2xvdWRTdG9yYWdlL0Ryb3Bib3gvU1dFTC9Db3BwZXJSaXZlckRlbHRhL1BvbmRUZW1wcy9EYXRhQW5hbHlzaXMvUG9uZFRlbXBzQW5hbHlzaXMiKQpgYGAKCiMgRXh0cmFjdGluZyB0aGUgUkNQIGRhdGEgZnJvbSB0aGUgYWF0IGZpbGUKCiMjIFJlYWQgaW4gdGhlIGRhdGEKCmBgYHtyfQpsb2FkKCJ+L0Ryb3Bib3gvU1dFTC9Db3BwZXJSaXZlckRlbHRhL1BvbmRUZW1wcy9EYXRhQW5hbHlzaXMvUG9uZFRlbXBzQW5hbHlzaXMvZm9yZWNhc3RlZF90ZW1wZXJhdHVyZS5SRGF0YSIpCgpzdHIoYWF0KQpgYGAKVGhpcyBjb21lcyBpbiBhcyBhIGRhdGFmaWxlIHdpdGggY29sdW1ucyB0ZW1wZXJhdHVyZSwgcmNwLCBtb2RlbCwgbW9udGgsIHllYXIsIHNpdGUsIGFuZCBkYXRlCgojIyBFeHRyYWN0IHRoZSBkYXRhCgpgYGB7cn0KIyBzZWxlY3RpbmcgQ1JECkNSRCA8LSBhYXQgJT4lCiAgZHBseXI6OmZpbHRlcihzaXRlID09ICJjb3JkIikKCiMgZmlsdGVyIGZvciBlYWNoIHJjcApDUl80LjUgPC0gQ1JEICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI0NSIpCgpDUl82LjAgPC0gQ1JEICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI2MCIpCgpDUl84LjUgPC0gQ1JEICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI4NSIpCgojIHNlbGVjdGluZyBZRgpZRiA8LSBhYXQgJT4lCiAgZHBseXI6OmZpbHRlcihzaXRlID09ICJ5YWsiKQoKIyBmaWx0ZXIgZm9yIGVhY2ggcmNwCllGXzQuNSA8LSBZRiAlPiUKICBkcGx5cjo6ZmlsdGVyKHJjcCA9PSAiNDUiKQoKWUZfNi4wIDwtIFlGICU+JQogIGRwbHlyOjpmaWx0ZXIocmNwID09ICI2MCIpCgpZRl84LjUgPC0gWUYlPiUKICBkcGx5cjo6ZmlsdGVyKHJjcCA9PSAiODUiKQpgYGAKCgpgYGB7cn0KZ2dwbG90KCkrCiAgIGdlb21fc21vb3RoKGRhdGEgPSBDUl84LjUsIGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXBlcmF0dXJlLCBjb2xvciA9ICJyZWQiKSkgKwogICBnZW9tX3Ntb290aChkYXRhID0gQ1JfNC41LCBhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wZXJhdHVyZSwgY29sb3IgPSAiYmx1ZSIpKQogCgoKYGBgCgojIyBTdGFydGluZyB3aXRoIHRoZSBSQ1AgNC41IGRhdGEgCgojIyMgRmlsdGVyaW5nIHRvIDQuNQpgYGB7cn0KQ1JfNC41CgojIEdyb3VwIGJ5IGRhdGUgKHllYXIgYW5kIG1vbnRoIGNvbWJpbmF0aW9uKSBhbmQgY2FsY3VsYXRlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUKYXZnX0NSXzQuNSA8LSBDUl80LjUgJT4lCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z190ZW1wZXJhdHVyZSA9IG1lYW4odGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHN0ZF90ZW1wZXJhdHVyZSA9IHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBwcmVjaXNpb24gPSAxIC8gKHNkKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpXjIpKQoKIyBWaWV3IHRoZSByZXN1bHRpbmcgZGF0YWZyYW1lCnByaW50KGF2Z19DUl80LjUpCgpDUl80LjUgPC0gYXZnX0NSXzQuNQpDUl80LjUKYGBgCgoKYGBge3J9CllGXzQuNQoKIyBHcm91cCBieSBkYXRlICh5ZWFyIGFuZCBtb250aCBjb21iaW5hdGlvbikgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIHRlbXBlcmF0dXJlCmF2Z19ZRl80LjUgPC0gWUZfNC41ICU+JQogIGdyb3VwX2J5KGRhdGUpICU+JQogIHN1bW1hcmlzZShhdmdfdGVtcGVyYXR1cmUgPSBtZWFuKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzdGRfdGVtcGVyYXR1cmUgPSBzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcHJlY2lzaW9uID0gMSAvIChzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKV4yKSkKCiMgVmlldyB0aGUgcmVzdWx0aW5nIGRhdGFmcmFtZQpwcmludChhdmdfWUZfNC41KQoKWUZfNC41IDwtIGF2Z19ZRl80LjUKWUZfNC41CmBgYAoKIyMjIFBsb3QgdGhlIGZvcmVjYXN0ZWQgZGF0YQoKYGBge3J9CkNSXzQuNQoKIyBGdWxsIHRpbWUgZnJhbWUgKDIwMDYtMjEwMCkKQ1JfU05BUCA8LSBnZ3Bsb3QoZGF0YSA9IENSXzQuNSwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSkpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBhdmdfdGVtcGVyYXR1cmUpLCBzaXplID0gMC44KSArICAjIExpbmUgcGxvdCBmb3IgYXZnX3RlbXBlcmF0dXJlCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBhdmdfdGVtcGVyYXR1cmUgLSBzdGRfdGVtcGVyYXR1cmUsIAogICAgICAgICAgICAgICAgICB5bWF4ID0gYXZnX3RlbXBlcmF0dXJlICsgc3RkX3RlbXBlcmF0dXJlKSwgICMgUmliYm9uIGZvciB1bmNlcnRhaW50eQogICAgICAgICAgICAgIGFscGhhID0gMC41LCBmaWxsID0gImJsdWUiKSArCiAgeGxhYigiWWVhciIpICsKICB5bGFiKCJNZWFuIEZvcmVjYXN0IFRlbXBlcmF0dXJlIikgKwogIGdndGl0bGUoIkNvcHBlciBSaXZlciBTTkFQIEZvcmVjYXN0IC0gUkNQIDQuNSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpDUl9TTkFQCgoKZ2dzYXZlKCJDUl9HZW9fRm9yZWNhc3Q0LjVfMjAyMC5qcGVnIiwgcGxvdCA9IENSX1NOQVAsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgoKYGBge3J9CllGXzQuNQoKIyBGdWxsIHRpbWUgZnJhbWUgKDIwMDYtMjEwMCkKWUZfU05BUCA8LSBnZ3Bsb3QoZGF0YSA9IFlGXzQuNSwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSkpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBhdmdfdGVtcGVyYXR1cmUpLCBzaXplID0gMC44KSArICAjIExpbmUgcGxvdCBmb3IgYXZnX3RlbXBlcmF0dXJlCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBhdmdfdGVtcGVyYXR1cmUgLSBzdGRfdGVtcGVyYXR1cmUsCiAgICAgICAgICAgICAgICAgIHltYXggPSBhdmdfdGVtcGVyYXR1cmUgKyBzdGRfdGVtcGVyYXR1cmUpLCAgIyBSaWJib24gZm9yIHVuY2VydGFpbnR5CiAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGZpbGwgPSAiYmx1ZSIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIk1lYW4gRm9yZWNhc3QgVGVtcGVyYXR1cmUiKSArCiAgZ2d0aXRsZSgiWWFrdXRhdCBGb3JlbGFuZCBTTkFQIEZvcmVjYXN0IC0gUkNQIDQuNSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpZRl9TTkFQCgoKZ2dzYXZlKCJZRl9HZW9fRm9yZWNhc3Q0LjVfMjAyMC5qcGVnIiwgcGxvdCA9IFlGX1NOQVAsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgojIyBDb250aW51aW5nIHdpdGggdGhlIFJDUCA2LjAgZGF0YQoKIyMjIEZpbHRlcmluZyB0byA2LjAKYGBge3J9CkNSXzYuMAoKIyBHcm91cCBieSBkYXRlICh5ZWFyIGFuZCBtb250aCBjb21iaW5hdGlvbikgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIHRlbXBlcmF0dXJlCmF2Z19DUl82LjAgPC0gQ1JfNi4wICU+JQogIGdyb3VwX2J5KGRhdGUpICU+JQogIHN1bW1hcmlzZShhdmdfdGVtcGVyYXR1cmUgPSBtZWFuKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzdGRfdGVtcGVyYXR1cmUgPSBzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcHJlY2lzaW9uID0gMSAvIChzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKV4yKSkKCiMgVmlldyB0aGUgcmVzdWx0aW5nIGRhdGFmcmFtZQpwcmludChhdmdfQ1JfNi4wKQoKQ1JfNi4wIDwtIGF2Z19DUl82LjAKQ1JfNi4wCmBgYAoKCmBgYHtyfQpZRl82LjAKCiMgR3JvdXAgYnkgZGF0ZSAoeWVhciBhbmQgbW9udGggY29tYmluYXRpb24pIGFuZCBjYWxjdWxhdGUgYXZlcmFnZSB0ZW1wZXJhdHVyZQphdmdfWUZfNi4wIDwtIFlGXzYuMCAlPiUKICBncm91cF9ieShkYXRlKSAlPiUKICBzdW1tYXJpc2UoYXZnX3RlbXBlcmF0dXJlID0gbWVhbih0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc3RkX3RlbXBlcmF0dXJlID0gc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHByZWNpc2lvbiA9IDEgLyAoc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSleMikpCgojIFZpZXcgdGhlIHJlc3VsdGluZyBkYXRhZnJhbWUKcHJpbnQoYXZnX1lGXzYuMCkKCllGXzYuMCA8LSBhdmdfWUZfNi4wCllGXzYuMApgYGAKCiMjIyBQbG90IHRoZSBmb3JlY2FzdGVkIGRhdGEKCmBgYHtyfQpDUl82LjAKCiMgRnVsbCB0aW1lIGZyYW1lICgyMDA2LTIxMDApCkNSX1NOQVAgPC0gZ2dwbG90KGRhdGEgPSBDUl82LjAsIG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUpKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gYXZnX3RlbXBlcmF0dXJlKSwgc2l6ZSA9IDAuOCkgKyAgIyBMaW5lIHBsb3QgZm9yIGF2Z190ZW1wZXJhdHVyZQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gYXZnX3RlbXBlcmF0dXJlIC0gc3RkX3RlbXBlcmF0dXJlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IGF2Z190ZW1wZXJhdHVyZSArIHN0ZF90ZW1wZXJhdHVyZSksICAjIFJpYmJvbiBmb3IgdW5jZXJ0YWludHkKICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwgZmlsbCA9ICJibHVlIikgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiTWVhbiBGb3JlY2FzdCBUZW1wZXJhdHVyZSIpICsKICBnZ3RpdGxlKCJDb3BwZXIgUml2ZXIgU05BUCBGb3JlY2FzdCAtIFJDUCA2LjAiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKQ1JfU05BUAoKCmdnc2F2ZSgiQ1JfR2VvX0ZvcmVjYXN0Ni4wXzIwMjAuanBlZyIsIHBsb3QgPSBDUl9TTkFQLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKYGBge3J9CllGXzYuMAoKIyBGdWxsIHRpbWUgZnJhbWUgKDIwMDYtMjEwMCkKWUZfU05BUCA8LSBnZ3Bsb3QoZGF0YSA9IFlGXzYuMCwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSkpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBhdmdfdGVtcGVyYXR1cmUpLCBzaXplID0gMC44KSArICAjIExpbmUgcGxvdCBmb3IgYXZnX3RlbXBlcmF0dXJlCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBhdmdfdGVtcGVyYXR1cmUgLSBzdGRfdGVtcGVyYXR1cmUsCiAgICAgICAgICAgICAgICAgIHltYXggPSBhdmdfdGVtcGVyYXR1cmUgKyBzdGRfdGVtcGVyYXR1cmUpLCAgIyBSaWJib24gZm9yIHVuY2VydGFpbnR5CiAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGZpbGwgPSAiYmx1ZSIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIk1lYW4gRm9yZWNhc3QgVGVtcGVyYXR1cmUiKSArCiAgZ2d0aXRsZSgiWWFrdXRhdCBGb3JlbGFuZCBTTkFQIEZvcmVjYXN0IC0gUkNQIDYuMCIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpZRl9TTkFQCgoKZ2dzYXZlKCJZRl9HZW9fRm9yZWNhc3Q2LjBfMjAyMC5qcGVnIiwgcGxvdCA9IFlGX1NOQVAsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgojIyBDb250aW51aW5nIHdpdGggdGhlIFJDUCA4LjUgZGF0YQoKIyMjIEZpbHRlcmluZyB0byA4LjUKYGBge3J9CkNSXzguNQoKIyBHcm91cCBieSBkYXRlICh5ZWFyIGFuZCBtb250aCBjb21iaW5hdGlvbikgYW5kIGNhbGN1bGF0ZSBhdmVyYWdlIHRlbXBlcmF0dXJlCmF2Z19DUl84LjUgPC0gQ1JfOC41ICU+JQogIGdyb3VwX2J5KGRhdGUpICU+JQogIHN1bW1hcmlzZShhdmdfdGVtcGVyYXR1cmUgPSBtZWFuKHRlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBzdGRfdGVtcGVyYXR1cmUgPSBzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgcHJlY2lzaW9uID0gMSAvIChzZCh0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKV4yKSkKCiMgVmlldyB0aGUgcmVzdWx0aW5nIGRhdGFmcmFtZQpwcmludChhdmdfQ1JfOC41KQoKQ1JfOC41IDwtIGF2Z19DUl84LjUKQ1JfOC41CmBgYAoKCmBgYHtyfQpZRl84LjUKCiMgR3JvdXAgYnkgZGF0ZSAoeWVhciBhbmQgbW9udGggY29tYmluYXRpb24pIGFuZCBjYWxjdWxhdGUgYXZlcmFnZSB0ZW1wZXJhdHVyZQphdmdfWUZfOC41IDwtIFlGXzguNSAlPiUKICBncm91cF9ieShkYXRlKSAlPiUKICBzdW1tYXJpc2UoYXZnX3RlbXBlcmF0dXJlID0gbWVhbih0ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc3RkX3RlbXBlcmF0dXJlID0gc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHByZWNpc2lvbiA9IDEgLyAoc2QodGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSleMikpCgojIFZpZXcgdGhlIHJlc3VsdGluZyBkYXRhZnJhbWUKcHJpbnQoYXZnX1lGXzguNSkKCllGXzguNSA8LSBhdmdfWUZfOC41CllGXzguNQpgYGAKCiMjIyBQbG90IHRoZSBmb3JlY2FzdGVkIGRhdGEKCmBgYHtyfQpDUl84LjUKCiMgRnVsbCB0aW1lIGZyYW1lICgyMDA2LTIxMDApCkNSX1NOQVAgPC0gZ2dwbG90KGRhdGEgPSBDUl84LjUsIG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUpKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gYXZnX3RlbXBlcmF0dXJlKSwgc2l6ZSA9IDAuOCkgKyAgIyBMaW5lIHBsb3QgZm9yIGF2Z190ZW1wZXJhdHVyZQogIGdlb21fcmliYm9uKGFlcyh5bWluID0gYXZnX3RlbXBlcmF0dXJlIC0gc3RkX3RlbXBlcmF0dXJlLCAKICAgICAgICAgICAgICAgICAgeW1heCA9IGF2Z190ZW1wZXJhdHVyZSArIHN0ZF90ZW1wZXJhdHVyZSksICAjIFJpYmJvbiBmb3IgdW5jZXJ0YWludHkKICAgICAgICAgICAgICBhbHBoYSA9IDAuNSwgZmlsbCA9ICJibHVlIikgKwogIHhsYWIoIlllYXIiKSArCiAgeWxhYigiTWVhbiBGb3JlY2FzdCBUZW1wZXJhdHVyZSIpICsKICBnZ3RpdGxlKCJDb3BwZXIgUml2ZXIgU05BUCBGb3JlY2FzdCAtIFJDUCA4LjUiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKQ1JfU05BUAoKCmdnc2F2ZSgiQ1JfR2VvX0ZvcmVjYXN0OC41XzIwMjAuanBlZyIsIHBsb3QgPSBDUl9TTkFQLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKYGBge3J9CllGXzguNQoKIyBGdWxsIHRpbWUgZnJhbWUgKDIwMDYtMjEwMCkKWUZfU05BUCA8LSBnZ3Bsb3QoZGF0YSA9IFlGXzguNSwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSkpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBhdmdfdGVtcGVyYXR1cmUpLCBzaXplID0gMC44KSArICAjIExpbmUgcGxvdCBmb3IgYXZnX3RlbXBlcmF0dXJlCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBhdmdfdGVtcGVyYXR1cmUgLSBzdGRfdGVtcGVyYXR1cmUsCiAgICAgICAgICAgICAgICAgIHltYXggPSBhdmdfdGVtcGVyYXR1cmUgKyBzdGRfdGVtcGVyYXR1cmUpLCAgIyBSaWJib24gZm9yIHVuY2VydGFpbnR5CiAgICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGZpbGwgPSAiYmx1ZSIpICsKICB4bGFiKCJZZWFyIikgKwogIHlsYWIoIk1lYW4gRm9yZWNhc3QgVGVtcGVyYXR1cmUiKSArCiAgZ2d0aXRsZSgiWWFrdXRhdCBGb3JlbGFuZCBTTkFQIEZvcmVjYXN0IC0gUkNQIDguNSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpZRl9TTkFQCgoKZ2dzYXZlKCJZRl9HZW9fRm9yZWNhc3Q4LjVfMjAyMC5qcGVnIiwgcGxvdCA9IFlGX1NOQVAsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgpTYXZpbmcgdGhlIGRhdGEgYXMgZGF0YWZpbGVzIGZvciBsYXRlciB1c2UKCmBgYHtyfQp3cml0ZS5jc3YoWUZfNC41LCBmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9ZRjQ1LmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQp3cml0ZS5jc3YoWUZfNi4wLCBmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9ZRjYwLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQp3cml0ZS5jc3YoWUZfOC41LCBmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9ZRjg1LmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKd3JpdGUuY3N2KENSXzQuNSwgZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I0NS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KENSXzYuMCwgZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I2MC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KENSXzguNSwgZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I4NS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgpJZiB0aGVzZSBhYm92ZSBpcyBhbHJlYWR5IGRvbmUsIHN0YXJ0IGhlcmUgYW5kIGp1c3QgcmVhZCBpbiB0aGUgZmlsZXMgdGhhdCB3ZXJlIGNyZWF0ZWQgXgpgYGB7cn0KWUZfNDUgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY0NS5jc3YiKQpZRl84NSA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9ZRjg1LmNzdiIpCgpDUl80NSA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9DUjQ1LmNzdiIpCkNSXzg1IDwtIHJlYWQuY3N2KGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX0NSODUuY3N2IikKCmBgYAoKUmVhZCBpbiB0aGUgZGF0YSBmaWxlIGZvciB0aGUgYWlycG9ydCB0ZW1wZXJhdHVyZSBkYXRhCiAgU2VwYXJhdGUgdGhpcyBieSBhaXJwb3J0IGxvY2F0aW9uCgpgYGB7cn0KQ1JEX2FpcnBvcnQgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9DUl9Qb25kQWlyVGVtcF9tZWFuLmNzdiIpCkNSRF9haXJwb3J0IDwtIENSRF9haXJwb3J0ICU+JQogIHNlbGVjdCgtWCkKCllGX2FpcnBvcnQgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9ZRl9Qb25kQWlyVGVtcF9tZWFuLmNzdiIpCllGX2FpcnBvcnQgPC0gWUZfYWlycG9ydCAlPiUKICBzZWxlY3QoLVgpCmBgYAoKIyBDb3BwZXIgUml2ZXIgUkNQIDQuNQoKUmVhZCBpbiB0aGUgZGF0YQpgYGB7cn0KIyBSZWFkIGRhdGEgZmlsZXMKQ1JfNDUgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I0NS5jc3YiKQpDUkRfYWlycG9ydCA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL0NSX1BvbmRBaXJUZW1wX21lYW4uY3N2IikKQ1JEX2FpcnBvcnQgPC0gQ1JEX2FpcnBvcnQgJT4lIHNlbGVjdCgtWCkgICMgUmVtb3ZlIHVubmVjZXNzYXJ5IGNvbHVtbiAnWCcKCmBgYAoKQ2hlY2sgZGF0ZXMKCmBgYHtyfQojIEZpeCAnZGF0ZScgaW4gQ1JfNDUgdG8gZW5zdXJlIGl0J3MgaW4gRGF0ZSBmb3JtYXQKQ1JfNDUkZGF0ZSA8LSBhcy5EYXRlKHBhc3RlKCIwMSIsIENSXzQ1JGRhdGUpLCBmb3JtYXQgPSAiJWQgJWIgJVkiKQoKIyBFbnN1cmUgdGhhdCB0aGVyZSBhcmUgbm8gTkFzIGluIHRoZSAnZGF0ZScgY29sdW1uIGFmdGVyIGNvbnZlcnNpb24Kc3VtKGlzLm5hKENSXzQ1JGRhdGUpKSAgIyBDaGVjayBpZiB0aGVyZSBhcmUgYW55IG1pc3NpbmcgdmFsdWVzIChzaG91bGQgYmUgMCkKCmBgYAoKVHJpbSBkYXRlcwoKYGBge3J9CiMgVHJpbSBDUl80NSB0byB0aGUgZGF0ZSByYW5nZSBvZiBDUkRfYWlycG9ydApzdGFydF9kYXRlIDwtIG1pbihDUkRfYWlycG9ydCREYXRlKQplbmRfZGF0ZSA8LSBtYXgoQ1JEX2FpcnBvcnQkRGF0ZSkKCiMgU3Vic2V0IENSXzQ1IHRvIG1hdGNoIHRoZSBkYXRlIHJhbmdlIG9mIENSRF9haXJwb3J0CkNSXzQ1X3RyaW1tZWQgPC0gQ1JfNDUgJT4lCiAgZmlsdGVyKGRhdGUgPj0gc3RhcnRfZGF0ZSAmIGRhdGUgPD0gZW5kX2RhdGUpCgpgYGAKClBsb3QgcHJlLWNvcnJlY3Rpb24gZGF0YQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgRW5zdXJlICdEYXRlJyBpbiBDUkRfYWlycG9ydCBpcyBpbiBEYXRlIGZvcm1hdApDUkRfYWlycG9ydCREYXRlIDwtIGFzLkRhdGUoQ1JEX2FpcnBvcnQkRGF0ZSkKCiMgQ2hlY2sgc3RydWN0dXJlIG9mIENSXzQ1X3RyaW1tZWQgdG8gY29uZmlybSBjb3JyZWN0IERhdGUgY29sdW1uCnN0cihDUl80NV90cmltbWVkKQoKIyBQbG90IE9ic2VydmVkIHZzIFVuY29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl80NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSRF9haXJwb3J0LCBhZXMoeCA9IERhdGUsIHkgPSBBaXJfTW9udGhBdmcsIGNvbG9yID0gIk9ic2VydmVkIiksIHNpemUgPSAxLjIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiT2JzZXJ2ZWQgdnMgVW5jb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIENSRCBSQ1AgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiT2JzZXJ2ZWQiID0gImJsYWNrIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9QcmUtQ29ycmVjdGlvbkNvbXBhcmlzb25fQ1I0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKei1zY29yZSBiaWFzIGNvcnJlY3Rpb24KCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIG9ic2VydmVkIGFuZCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzCm11X29icyA8LSBtZWFuKENSRF9haXJwb3J0JEFpcl9Nb250aEF2ZywgbmEucm0gPSBUUlVFKQpzaWdtYV9vYnMgPC0gc2QoQ1JEX2FpcnBvcnQkQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCgptdV9wcmVkIDwtIG1lYW4oQ1JfNDVfdHJpbW1lZCRhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKc2lnbWFfcHJlZCA8LSBzZChDUl80NV90cmltbWVkJGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKQoKYGBgCgpDb3JyZWN0aW9uIGFwcGxpZWQgdG8gdGhlIDIwMTItMjAyMCBkYXRhc2V0CgpgYGB7cn0KIyBBcHBseSB0aGUgei1zY29yZSBiaWFzIGNvcnJlY3Rpb24gdG8gdGhlIHByZWRpY3RlZCBkYXRhCkNSXzQ1X3RyaW1tZWQkY29ycmVjdGVkX3RlbXAgPC0gKENSXzQ1X3RyaW1tZWQkYXZnX3RlbXBlcmF0dXJlIC0gbXVfcHJlZCkgLyBzaWdtYV9wcmVkICogc2lnbWFfb2JzICsgbXVfb2JzCgojIENoZWNrIHRoZSBmaXJzdCBmZXcgcm93cyB0byB2ZXJpZnkKaGVhZChDUl80NV90cmltbWVkKQoKYGBgCgpQbG90IGNvcnJlY3RlZCBhbmQgb2JzZXJ2ZWQgdmFsdWVzCgpgYGB7cn0KIyBQbG90dGluZyBPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcwpQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzQ1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fbGluZShkYXRhID0gQ1JEX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIENSRCBSQ1AgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIsICJPYnNlcnZlZCIgPSAiYmxhY2siKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGVkX0NSNDUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKUGxvdHRpbmcgdGhlIHZhbHVlcyBoZXJlCgpgYGB7cn0KIyBQbG90IE9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIChObyBPYnNlcnZlZCBWYWx1ZXMpClBsb3QgPC0gZ2dwbG90KCkgKwogICMgUGxvdCB0aGUgb3JpZ2luYWwgcHJlZGljdGVkIHRlbXBlcmF0dXJlcyAodW5jb3JyZWN0ZWQpCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl80NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gInNvbGlkIikgKwogIAogICMgUGxvdCB0aGUgY29ycmVjdGVkIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMKICBnZW9tX2xpbmUoZGF0YSA9IENSXzQ1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIAogICMgU2V0IHBsb3QgbGFiZWxzCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1JEIFJDUCA0LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICAKICAjIEN1c3RvbWl6ZSB4LWF4aXMgdG8gc2hvdyBtb250aHMveWVhcnMgY2xlYXJseQogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIAogICMgRGVmaW5lIGN1c3RvbSBjb2xvcnMgZm9yIHRoZSBwbG90CiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICAKICAjIE1pbmltYWwgdGhlbWUgZm9yIHRoZSBwbG90CiAgdGhlbWVfbWluaW1hbCgpICsKICAKICAjIEN1c3RvbWl6YXRpb25zIGZvciBhcHBlYXJhbmNlCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLCAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgY2xhcml0eQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0NvcnJlY3RlZENvbXBhcmlzb25fQ1I0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYApDb3JyZWN0aW9uIGFwcGxpZWQgdG8gdGhlIHdob2xlIGRhdGFzZXQKCmBgYHtyfQojIEFwcGx5IHRoZSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbiB0byB0aGUgcHJlZGljdGVkIGRhdGEKQ1JfNDUkY29ycmVjdGVkX3RlbXAgPC0gKENSXzQ1JGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwoKIyBDaGVjayB0aGUgZmlyc3QgZmV3IHJvd3MgdG8gdmVyaWZ5CmhlYWQoQ1JfNDUpCmBgYAoKUGxvdCB0aGlzIHRvIG1ha2UgaXQgaW50byB0aGUgc2FtZSBwcmVkaWN0ZWQgKGNvcnJlY3RlZCkgKyBwcmVkaWN0ZWQgKHVuY29ycmVjdGVkKSB3aXRoIHRoZSBlcnJvciBpbmNsdWRlZAoKYGBge3J9CiMgUGxvdCBPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAoTm8gT2JzZXJ2ZWQgVmFsdWVzKQpQbG90IDwtIGdncGxvdCgpICsKICAjIFBsb3QgdGhlIG9yaWdpbmFsIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMgKHVuY29ycmVjdGVkKQogIGdlb21fbGluZShkYXRhID0gQ1JfNDUsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAic29saWQiKSArCiAgCiAgIyBQbG90IHRoZSBjb3JyZWN0ZWQgcHJlZGljdGVkIHRlbXBlcmF0dXJlcwogIGdlb21fbGluZShkYXRhID0gQ1JfNDUsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIAogIGdlb21fbGluZShkYXRhID0gQ1JEX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIAogICMgU2V0IHBsb3QgbGFiZWxzCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1JEIFJDUCA0LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICAKICAjIEN1c3RvbWl6ZSB4LWF4aXMgdG8gc2hvdyBtb250aHMveWVhcnMgY2xlYXJseQogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIAogICMgRGVmaW5lIGN1c3RvbSBjb2xvcnMgZm9yIHRoZSBwbG90CiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICAKICAjIE1pbmltYWwgdGhlbWUgZm9yIHRoZSBwbG90CiAgdGhlbWVfbWluaW1hbCgpICsKICAKICAjIEN1c3RvbWl6YXRpb25zIGZvciBhcHBlYXJhbmNlCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLCAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgY2xhcml0eQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0Z1bGxDb3JyZWN0aW9uX0NSNDUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKClNhdmUgdGhlIG5ldyBmaWxlCgpgYGB7cn0KIyBTYXZlIHRoZSB1cGRhdGVkIGRhdGFzZXQgd2l0aCB0aGUgY29ycmVjdGVkIHRlbXBlcmF0dXJlcyB0byBhIG5ldyBDU1YgZmlsZQp3cml0ZS5jc3YoQ1JfNDUsICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfQ1I0NV9jb3JyZWN0ZWQuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCiMgQ29wcGVyIFJpdmVyIFJDUCA4LjUKClJlYWQgaW4gdGhlIGRhdGEKYGBge3J9CiMgUmVhZCBkYXRhIGZpbGVzCkNSXzg1IDwtIHJlYWQuY3N2KGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX0NSODUuY3N2IikKQ1JEX2FpcnBvcnQgPC0gcmVhZC5jc3YoZmlsZSA9ICJCaWFzQ29ycmVjdGlvbi9DUl9Qb25kQWlyVGVtcF9tZWFuLmNzdiIpCkNSRF9haXJwb3J0IDwtIENSRF9haXJwb3J0ICU+JSBzZWxlY3QoLVgpICAjIFJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW4gJ1gnCgpgYGAKCkNoZWNrIGRhdGVzCgpgYGB7cn0KIyBGaXggJ2RhdGUnIGluIENSXzg1IHRvIGVuc3VyZSBpdCdzIGluIERhdGUgZm9ybWF0CkNSXzg1JGRhdGUgPC0gYXMuRGF0ZShwYXN0ZSgiMDEiLCBDUl84NSRkYXRlKSwgZm9ybWF0ID0gIiVkICViICVZIikKCiMgRW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIE5BcyBpbiB0aGUgJ2RhdGUnIGNvbHVtbiBhZnRlciBjb252ZXJzaW9uCnN1bShpcy5uYShDUl84NSRkYXRlKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBtaXNzaW5nIHZhbHVlcyAoc2hvdWxkIGJlIDApCgpgYGAKClRyaW0gZGF0ZXMKCmBgYHtyfQojIFRyaW0gQ1JfODUgdG8gdGhlIGRhdGUgcmFuZ2Ugb2YgQ1JEX2FpcnBvcnQKc3RhcnRfZGF0ZSA8LSBtaW4oQ1JEX2FpcnBvcnQkRGF0ZSkKZW5kX2RhdGUgPC0gbWF4KENSRF9haXJwb3J0JERhdGUpCgojIFN1YnNldCBDUl84NSB0byBtYXRjaCB0aGUgZGF0ZSByYW5nZSBvZiBDUkRfYWlycG9ydApDUl84NV90cmltbWVkIDwtIENSXzg1ICU+JQogIGZpbHRlcihkYXRlID49IHN0YXJ0X2RhdGUgJiBkYXRlIDw9IGVuZF9kYXRlKQoKYGBgCgpQbG90IHByZS1jb3JyZWN0aW9uIGRhdGEKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIEVuc3VyZSAnRGF0ZScgaW4gQ1JEX2FpcnBvcnQgaXMgaW4gRGF0ZSBmb3JtYXQKQ1JEX2FpcnBvcnQkRGF0ZSA8LSBhcy5EYXRlKENSRF9haXJwb3J0JERhdGUpCgojIENoZWNrIHN0cnVjdHVyZSBvZiBDUl84NV90cmltbWVkIHRvIGNvbmZpcm0gY29ycmVjdCBEYXRlIGNvbHVtbgpzdHIoQ1JfODVfdHJpbW1lZCkKCiMgUGxvdCBPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzClBsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gQ1JfODVfdHJpbW1lZCwgYWVzKHggPSBkYXRlLCB5ID0gYXZnX3RlbXBlcmF0dXJlLCBjb2xvciA9ICJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIpLCBzaXplID0gMS4yKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBDUkRfYWlycG9ydCwgYWVzKHggPSBEYXRlLCB5ID0gQWlyX01vbnRoQXZnLCBjb2xvciA9ICJPYnNlcnZlZCIpLCBzaXplID0gMS4yKSArCiAgbGFicygKICAgIHRpdGxlID0gIk9ic2VydmVkIHZzIFVuY29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBDUkQgUkNQIDguNSIsCiAgICB4ID0gIkRhdGUiLAogICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBUeXBlIgogICkgKwogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIk9ic2VydmVkIiA9ICJibGFjayIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gODUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvUHJlLUNvcnJlY3Rpb25Db21wYXJpc29uX0NSODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKei1zY29yZSBiaWFzIGNvcnJlY3Rpb24KCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIG9ic2VydmVkIGFuZCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzCm11X29icyA8LSBtZWFuKENSRF9haXJwb3J0JEFpcl9Nb250aEF2ZywgbmEucm0gPSBUUlVFKQpzaWdtYV9vYnMgPC0gc2QoQ1JEX2FpcnBvcnQkQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCgptdV9wcmVkIDwtIG1lYW4oQ1JfODVfdHJpbW1lZCRhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKc2lnbWFfcHJlZCA8LSBzZChDUl84NV90cmltbWVkJGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKQoKYGBgCgpDb3JyZWN0aW9uIGFwcGxpZWQgdG8gdGhlIDIwMTItMjAyMCBkYXRhc2V0CgpgYGB7cn0KIyBBcHBseSB0aGUgei1zY29yZSBiaWFzIGNvcnJlY3Rpb24gdG8gdGhlIHByZWRpY3RlZCBkYXRhCkNSXzg1X3RyaW1tZWQkY29ycmVjdGVkX3RlbXAgPC0gKENSXzg1X3RyaW1tZWQkYXZnX3RlbXBlcmF0dXJlIC0gbXVfcHJlZCkgLyBzaWdtYV9wcmVkICogc2lnbWFfb2JzICsgbXVfb2JzCgojIENoZWNrIHRoZSBmaXJzdCBmZXcgcm93cyB0byB2ZXJpZnkKaGVhZChDUl84NV90cmltbWVkKQoKYGBgCgpQbG90IGNvcnJlY3RlZCBhbmQgb2JzZXJ2ZWQgdmFsdWVzCgpgYGB7cn0KIyBQbG90dGluZyBPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcwpQbG90IDwtIGdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IENSXzg1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21fbGluZShkYXRhID0gQ1JEX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIENSRCBSQ1AgOC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIsICJPYnNlcnZlZCIgPSAiYmxhY2siKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDg1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGVkX0NSODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKUGxvdHRpbmcgdGhlIHZhbHVlcyBoZXJlCgpgYGB7cn0KIyBQbG90IE9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIChObyBPYnNlcnZlZCBWYWx1ZXMpClBsb3QgPC0gZ2dwbG90KCkgKwogICMgUGxvdCB0aGUgb3JpZ2luYWwgcHJlZGljdGVkIHRlbXBlcmF0dXJlcyAodW5jb3JyZWN0ZWQpCiAgZ2VvbV9saW5lKGRhdGEgPSBDUl84NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gInNvbGlkIikgKwogIAogICMgUGxvdCB0aGUgY29ycmVjdGVkIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMKICBnZW9tX2xpbmUoZGF0YSA9IENSXzg1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIAogICMgU2V0IHBsb3QgbGFiZWxzCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1JEIFJDUCA4LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICAKICAjIEN1c3RvbWl6ZSB4LWF4aXMgdG8gc2hvdyBtb250aHMveWVhcnMgY2xlYXJseQogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIAogICMgRGVmaW5lIGN1c3RvbSBjb2xvcnMgZm9yIHRoZSBwbG90CiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICAKICAjIE1pbmltYWwgdGhlbWUgZm9yIHRoZSBwbG90CiAgdGhlbWVfbWluaW1hbCgpICsKICAKICAjIEN1c3RvbWl6YXRpb25zIGZvciBhcHBlYXJhbmNlCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDg1LCBoanVzdCA9IDEpLCAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgY2xhcml0eQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0NvcnJlY3RlZENvbXBhcmlzb25fQ1I4NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYApDb3JyZWN0aW9uIGFwcGxpZWQgdG8gdGhlIHdob2xlIGRhdGFzZXQKCmBgYHtyfQojIEFwcGx5IHRoZSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbiB0byB0aGUgcHJlZGljdGVkIGRhdGEKQ1JfODUkY29ycmVjdGVkX3RlbXAgPC0gKENSXzg1JGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwoKIyBDaGVjayB0aGUgZmlyc3QgZmV3IHJvd3MgdG8gdmVyaWZ5CmhlYWQoQ1JfODUpCmBgYAoKUGxvdCB0aGlzIHRvIG1ha2UgaXQgaW50byB0aGUgc2FtZSBwcmVkaWN0ZWQgKGNvcnJlY3RlZCkgKyBwcmVkaWN0ZWQgKHVuY29ycmVjdGVkKSB3aXRoIHRoZSBlcnJvciBpbmNsdWRlZAoKYGBge3J9CiMgUGxvdCBPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAoTm8gT2JzZXJ2ZWQgVmFsdWVzKQpQbG90IDwtIGdncGxvdCgpICsKICAjIFBsb3QgdGhlIG9yaWdpbmFsIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMgKHVuY29ycmVjdGVkKQogIGdlb21fbGluZShkYXRhID0gQ1JfODUsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAic29saWQiKSArCiAgCiAgIyBQbG90IHRoZSBjb3JyZWN0ZWQgcHJlZGljdGVkIHRlbXBlcmF0dXJlcwogIGdlb21fbGluZShkYXRhID0gQ1JfODUsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIAogIGdlb21fbGluZShkYXRhID0gQ1JEX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIAogICMgU2V0IHBsb3QgbGFiZWxzCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gQ1JEIFJDUCA4LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICAKICAjIEN1c3RvbWl6ZSB4LWF4aXMgdG8gc2hvdyBtb250aHMveWVhcnMgY2xlYXJseQogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIAogICMgRGVmaW5lIGN1c3RvbSBjb2xvcnMgZm9yIHRoZSBwbG90CiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICAKICAjIE1pbmltYWwgdGhlbWUgZm9yIHRoZSBwbG90CiAgdGhlbWVfbWluaW1hbCgpICsKICAKICAjIEN1c3RvbWl6YXRpb25zIGZvciBhcHBlYXJhbmNlCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDg1LCBoanVzdCA9IDEpLCAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgY2xhcml0eQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0Z1bGxDb3JyZWN0aW9uX0NSODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKU2F2ZSB0aGUgbmV3IGZpbGUKCmBgYHtyfQojIFNhdmUgdGhlIHVwZGF0ZWQgZGF0YXNldCB3aXRoIHRoZSBjb3JyZWN0ZWQgdGVtcGVyYXR1cmVzIHRvIGEgbmV3IENTViBmaWxlCndyaXRlLmNzdihDUl84NSwgIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9EYXRhRmlsZXMvU05BUF9DUjg1X2NvcnJlY3RlZC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCmBgYAoKIyBZYWt1dGF0IEZvcmVsYW5kIFJDUCA0LjUKClJlYWQgaW4gdGhlIGRhdGEKYGBge3J9CiMgUmVhZCBkYXRhIGZpbGVzCllGXzQ1IDwtIHJlYWQuY3N2KGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX1lGNDUuY3N2IikKWUZfYWlycG9ydCA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL1lGX1BvbmRBaXJUZW1wX21lYW4uY3N2IikKWUZfYWlycG9ydCA8LSBZRl9haXJwb3J0ICU+JSBzZWxlY3QoLVgpICAjIFJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW4gJ1gnCgpgYGAKCkNoZWNrIGRhdGVzCgpgYGB7cn0KIyBGaXggJ2RhdGUnIGluIFlGXzQ1IHRvIGVuc3VyZSBpdCdzIGluIERhdGUgZm9ybWF0CllGXzQ1JGRhdGUgPC0gYXMuRGF0ZShwYXN0ZSgiMDEiLCBZRl80NSRkYXRlKSwgZm9ybWF0ID0gIiVkICViICVZIikKCiMgRW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIE5BcyBpbiB0aGUgJ2RhdGUnIGNvbHVtbiBhZnRlciBjb252ZXJzaW9uCnN1bShpcy5uYShZRl80NSRkYXRlKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBtaXNzaW5nIHZhbHVlcyAoc2hvdWxkIGJlIDApCgpgYGAKClRyaW0gZGF0ZXMKCmBgYHtyfQojIFRyaW0gWUZfNDUgdG8gdGhlIGRhdGUgcmFuZ2Ugb2YgWUZfYWlycG9ydApzdGFydF9kYXRlIDwtIG1pbihZRl9haXJwb3J0JERhdGUpCmVuZF9kYXRlIDwtIG1heChZRl9haXJwb3J0JERhdGUpCgojIFN1YnNldCBZRl80NSB0byBtYXRjaCB0aGUgZGF0ZSByYW5nZSBvZiBZRl9haXJwb3J0CllGXzQ1X3RyaW1tZWQgPC0gWUZfNDUgJT4lCiAgZmlsdGVyKGRhdGUgPj0gc3RhcnRfZGF0ZSAmIGRhdGUgPD0gZW5kX2RhdGUpCgpgYGAKClBsb3QgcHJlLWNvcnJlY3Rpb24gZGF0YQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgRW5zdXJlICdEYXRlJyBpbiBZRl9haXJwb3J0IGlzIGluIERhdGUgZm9ybWF0CllGX2FpcnBvcnQkRGF0ZSA8LSBhcy5EYXRlKFlGX2FpcnBvcnQkRGF0ZSkKCiMgQ2hlY2sgc3RydWN0dXJlIG9mIFlGXzQ1X3RyaW1tZWQgdG8gY29uZmlybSBjb3JyZWN0IERhdGUgY29sdW1uCnN0cihZRl80NV90cmltbWVkKQoKIyBQbG90IE9ic2VydmVkIHZzIFVuY29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl80NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gWUYgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiT2JzZXJ2ZWQiID0gImJsYWNrIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9QcmUtQ29ycmVjdGlvbkNvbXBhcmlzb25fWUY0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKCmBgYAoKei1zY29yZSBiaWFzIGNvcnJlY3Rpb24KCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIG9ic2VydmVkIGFuZCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzCm11X29icyA8LSBtZWFuKFlGX2FpcnBvcnQkQWlyX01vbnRoQXZnLCBuYS5ybSA9IFRSVUUpCnNpZ21hX29icyA8LSBzZChZRl9haXJwb3J0JEFpcl9Nb250aEF2ZywgbmEucm0gPSBUUlVFKQoKbXVfcHJlZCA8LSBtZWFuKFlGXzQ1X3RyaW1tZWQkYXZnX3RlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpCnNpZ21hX3ByZWQgPC0gc2QoWUZfNDVfdHJpbW1lZCRhdmdfdGVtcGVyYXR1cmUsIG5hLnJtID0gVFJVRSkKCmBgYAoKQ29ycmVjdGlvbiBhcHBsaWVkIHRvIHRoZSAyMDEyLTIwMjAgZGF0YXNldAoKYGBge3J9CiMgQXBwbHkgdGhlIHotc2NvcmUgYmlhcyBjb3JyZWN0aW9uIHRvIHRoZSBwcmVkaWN0ZWQgZGF0YQpZRl80NV90cmltbWVkJGNvcnJlY3RlZF90ZW1wIDwtIChZRl80NV90cmltbWVkJGF2Z190ZW1wZXJhdHVyZSAtIG11X3ByZWQpIC8gc2lnbWFfcHJlZCAqIHNpZ21hX29icyArIG11X29icwoKIyBDaGVjayB0aGUgZmlyc3QgZmV3IHJvd3MgdG8gdmVyaWZ5CmhlYWQoWUZfNDVfdHJpbW1lZCkKCmBgYAoKUGxvdCBjb3JyZWN0ZWQgYW5kIG9ic2VydmVkIHZhbHVlcwoKYGBge3J9CiMgUGxvdHRpbmcgT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl80NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA0LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICBzY2FsZV94X2RhdGUoCiAgICBkYXRlX2xhYmVscyA9ICIlYiAlWSIsICAgICMgRm9ybWF0IHgtYXhpcyBhcyBNb250aC1ZZWFyCiAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgICMgU2V0IGJyZWFrcyBldmVyeSBtb250aAogICAgZXhwYW5kID0gYygwLCAwKSAgICAgICAgICAjIFJlbW92ZSBleHRyYSBzcGFjZSBhdCB0aGUgZWRnZXMKICApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIiwgIk9ic2VydmVkIiA9ICJibGFjayIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gIml0YWxpYyIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9Db3JyZWN0ZWRfWUY0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgpQbG90dGluZyB0aGUgdmFsdWVzIGhlcmUKCmBgYHtyfQojIFBsb3QgT3JpZ2luYWwgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgKE5vIE9ic2VydmVkIFZhbHVlcykKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgIyBQbG90IHRoZSBvcmlnaW5hbCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzICh1bmNvcnJlY3RlZCkKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzQ1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGF2Z190ZW1wZXJhdHVyZSwgY29sb3IgPSAiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAic29saWQiKSArCiAgCiAgIyBQbG90IHRoZSBjb3JyZWN0ZWQgcHJlZGljdGVkIHRlbXBlcmF0dXJlcwogIGdlb21fbGluZShkYXRhID0gWUZfNDVfdHJpbW1lZCwgYWVzKHggPSBkYXRlLCB5ID0gY29ycmVjdGVkX3RlbXAsIGNvbG9yID0gIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgCiAgIyBTZXQgcGxvdCBsYWJlbHMKICBsYWJzKAogICAgdGl0bGUgPSAiT3JpZ2luYWwgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBZRiBSQ1AgNC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgCiAgIyBDdXN0b21pemUgeC1heGlzIHRvIHNob3cgbW9udGhzL3llYXJzIGNsZWFybHkKICBzY2FsZV94X2RhdGUoCiAgICBkYXRlX2xhYmVscyA9ICIlYiAlWSIsICAgICMgRm9ybWF0IHgtYXhpcyBhcyBNb250aC1ZZWFyCiAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwgICMgU2V0IGJyZWFrcyBldmVyeSBtb250aAogICAgZXhwYW5kID0gYygwLCAwKSAgICAgICAgICAjIFJlbW92ZSBleHRyYSBzcGFjZSBhdCB0aGUgZWRnZXMKICApICsKICAKICAjIERlZmluZSBjdXN0b20gY29sb3JzIGZvciB0aGUgcGxvdAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIpKSArCiAgCiAgIyBNaW5pbWFsIHRoZW1lIGZvciB0aGUgcGxvdAogIHRoZW1lX21pbmltYWwoKSArCiAgCiAgIyBDdXN0b21pemF0aW9ucyBmb3IgYXBwZWFyYW5jZQogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwgICMgUm90YXRlIHgtYXhpcyBsYWJlbHMgZm9yIGNsYXJpdHkKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApCiAgKQpQbG90CgpnZ3NhdmUoIkJpYXNDb3JyZWN0aW9uL0dlb19CaWFzQ29ycmVjdGlvbi9QbG90cy9Db3JyZWN0ZWRDb21wYXJpc29uX1lGNDUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKQ29ycmVjdGlvbiBhcHBsaWVkIHRvIHRoZSB3aG9sZSBkYXRhc2V0CgpgYGB7cn0KIyBBcHBseSB0aGUgei1zY29yZSBiaWFzIGNvcnJlY3Rpb24gdG8gdGhlIHByZWRpY3RlZCBkYXRhCllGXzQ1JGNvcnJlY3RlZF90ZW1wIDwtIChZRl80NSRhdmdfdGVtcGVyYXR1cmUgLSBtdV9wcmVkKSAvIHNpZ21hX3ByZWQgKiBzaWdtYV9vYnMgKyBtdV9vYnMKCiMgQ2hlY2sgdGhlIGZpcnN0IGZldyByb3dzIHRvIHZlcmlmeQpoZWFkKFlGXzQ1KQpgYGAKClBsb3QgdGhpcyB0byBtYWtlIGl0IGludG8gdGhlIHNhbWUgcHJlZGljdGVkIChjb3JyZWN0ZWQpICsgcHJlZGljdGVkICh1bmNvcnJlY3RlZCkgd2l0aCB0aGUgZXJyb3IgaW5jbHVkZWQKCmBgYHtyfQojIFBsb3QgT3JpZ2luYWwgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgKE5vIE9ic2VydmVkIFZhbHVlcykKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgIyBQbG90IHRoZSBvcmlnaW5hbCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzICh1bmNvcnJlY3RlZCkKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzQ1LCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gInNvbGlkIikgKwogIAogICMgUGxvdCB0aGUgY29ycmVjdGVkIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzQ1LCBhZXMoeCA9IGRhdGUsIHkgPSBjb3JyZWN0ZWRfdGVtcCwgY29sb3IgPSAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIAogICMgU2V0IHBsb3QgbGFiZWxzCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gWUYgUkNQIDQuNSIsCiAgICB4ID0gIkRhdGUiLAogICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBUeXBlIgogICkgKwogIAogICMgQ3VzdG9taXplIHgtYXhpcyB0byBzaG93IG1vbnRocy95ZWFycyBjbGVhcmx5CiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgCiAgIyBEZWZpbmUgY3VzdG9tIGNvbG9ycyBmb3IgdGhlIHBsb3QKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiID0gInJlZCIsICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiID0gImJsdWUiKSkgKwogIAogICMgTWluaW1hbCB0aGVtZSBmb3IgdGhlIHBsb3QKICB0aGVtZV9taW5pbWFsKCkgKwogIAogICMgQ3VzdG9taXphdGlvbnMgZm9yIGFwcGVhcmFuY2UKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBjbGFyaXR5CiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvRnVsbENvcnJlY3Rpb25fWUY0NS5qcGVnIiwgcGxvdCA9IFBsb3QsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKYGBgCgpTYXZlIHRoZSBuZXcgZmlsZQoKYGBge3J9CiMgU2F2ZSB0aGUgdXBkYXRlZCBkYXRhc2V0IHdpdGggdGhlIGNvcnJlY3RlZCB0ZW1wZXJhdHVyZXMgdG8gYSBuZXcgQ1NWIGZpbGUKd3JpdGUuY3N2KFlGXzQ1LCAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX1lGNDVfY29ycmVjdGVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKYGBgCgoKIyBZYWt1dGF0IEZvcmVsYW5kIFJDUCA4LjUKClJlYWQgaW4gdGhlIGRhdGEKYGBge3J9CiMgUmVhZCBkYXRhIGZpbGVzCllGXzg1IDwtIHJlYWQuY3N2KGZpbGUgPSAiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL0RhdGFGaWxlcy9TTkFQX1lGODUuY3N2IikKWUZfYWlycG9ydCA8LSByZWFkLmNzdihmaWxlID0gIkJpYXNDb3JyZWN0aW9uL1lGX1BvbmRBaXJUZW1wX21lYW4uY3N2IikKWUZfYWlycG9ydCA8LSBZRl9haXJwb3J0ICU+JSBzZWxlY3QoLVgpICAjIFJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW4gJ1gnCgpgYGAKCkNoZWNrIGRhdGVzCgpgYGB7cn0KIyBGaXggJ2RhdGUnIGluIFlGXzg1IHRvIGVuc3VyZSBpdCdzIGluIERhdGUgZm9ybWF0CllGXzg1JGRhdGUgPC0gYXMuRGF0ZShwYXN0ZSgiMDEiLCBZRl84NSRkYXRlKSwgZm9ybWF0ID0gIiVkICViICVZIikKCiMgRW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIE5BcyBpbiB0aGUgJ2RhdGUnIGNvbHVtbiBhZnRlciBjb252ZXJzaW9uCnN1bShpcy5uYShZRl84NSRkYXRlKSkgICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBtaXNzaW5nIHZhbHVlcyAoc2hvdWxkIGJlIDApCgpgYGAKClRyaW0gZGF0ZXMKCmBgYHtyfQojIFRyaW0gWUZfODUgdG8gdGhlIGRhdGUgcmFuZ2Ugb2YgWUZfYWlycG9ydApzdGFydF9kYXRlIDwtIG1pbihZRl9haXJwb3J0JERhdGUpCmVuZF9kYXRlIDwtIG1heChZRl9haXJwb3J0JERhdGUpCgojIFN1YnNldCBZRl84NSB0byBtYXRjaCB0aGUgZGF0ZSByYW5nZSBvZiBZRl9haXJwb3J0CllGXzg1X3RyaW1tZWQgPC0gWUZfODUgJT4lCiAgZmlsdGVyKGRhdGUgPj0gc3RhcnRfZGF0ZSAmIGRhdGUgPD0gZW5kX2RhdGUpCgpgYGAKClBsb3QgcHJlLWNvcnJlY3Rpb24gZGF0YQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgRW5zdXJlICdEYXRlJyBpbiBZRl9haXJwb3J0IGlzIGluIERhdGUgZm9ybWF0CllGX2FpcnBvcnQkRGF0ZSA8LSBhcy5EYXRlKFlGX2FpcnBvcnQkRGF0ZSkKCiMgQ2hlY2sgc3RydWN0dXJlIG9mIFlGXzg1X3RyaW1tZWQgdG8gY29uZmlybSBjb3JyZWN0IERhdGUgY29sdW1uCnN0cihZRl84NV90cmltbWVkKQoKIyBQbG90IE9ic2VydmVkIHZzIFVuY29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMKUGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl84NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlGX2FpcnBvcnQsIGFlcyh4ID0gRGF0ZSwgeSA9IEFpcl9Nb250aEF2ZywgY29sb3IgPSAiT2JzZXJ2ZWQiKSwgc2l6ZSA9IDEuMikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJPYnNlcnZlZCB2cyBVbmNvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gWUYgUkNQIDguNSIsCiAgICB4ID0gIkRhdGUiLAogICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBUeXBlIgogICkgKwogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIgPSAicmVkIiwgIk9ic2VydmVkIiA9ICJibGFjayIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gODUsIGhqdXN0ID0gMSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvUHJlLUNvcnJlY3Rpb25Db21wYXJpc29uX1lGODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCgpgYGAKCnotc2NvcmUgYmlhcyBjb3JyZWN0aW9uCgpgYGB7cn0KIyBDYWxjdWxhdGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGZvciBvYnNlcnZlZCBhbmQgcHJlZGljdGVkIHRlbXBlcmF0dXJlcwptdV9vYnMgPC0gbWVhbihZRl9haXJwb3J0JEFpcl9Nb250aEF2ZywgbmEucm0gPSBUUlVFKQpzaWdtYV9vYnMgPC0gc2QoWUZfYWlycG9ydCRBaXJfTW9udGhBdmcsIG5hLnJtID0gVFJVRSkKCm11X3ByZWQgPC0gbWVhbihZRl84NV90cmltbWVkJGF2Z190ZW1wZXJhdHVyZSwgbmEucm0gPSBUUlVFKQpzaWdtYV9wcmVkIDwtIHNkKFlGXzg1X3RyaW1tZWQkYXZnX3RlbXBlcmF0dXJlLCBuYS5ybSA9IFRSVUUpCgpgYGAKCkNvcnJlY3Rpb24gYXBwbGllZCB0byB0aGUgMjAxMi0yMDIwIGRhdGFzZXQKCmBgYHtyfQojIEFwcGx5IHRoZSB6LXNjb3JlIGJpYXMgY29ycmVjdGlvbiB0byB0aGUgcHJlZGljdGVkIGRhdGEKWUZfODVfdHJpbW1lZCRjb3JyZWN0ZWRfdGVtcCA8LSAoWUZfODVfdHJpbW1lZCRhdmdfdGVtcGVyYXR1cmUgLSBtdV9wcmVkKSAvIHNpZ21hX3ByZWQgKiBzaWdtYV9vYnMgKyBtdV9vYnMKCiMgQ2hlY2sgdGhlIGZpcnN0IGZldyByb3dzIHRvIHZlcmlmeQpoZWFkKFlGXzg1X3RyaW1tZWQpCgpgYGAKClBsb3QgY29ycmVjdGVkIGFuZCBvYnNlcnZlZCB2YWx1ZXMKCmBgYHtyfQojIFBsb3R0aW5nIE9ic2VydmVkIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzClBsb3QgPC0gZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gWUZfODVfdHJpbW1lZCwgYWVzKHggPSBkYXRlLCB5ID0gY29ycmVjdGVkX3RlbXAsIGNvbG9yID0gIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl9haXJwb3J0LCBhZXMoeCA9IERhdGUsIHkgPSBBaXJfTW9udGhBdmcsIGNvbG9yID0gIk9ic2VydmVkIiksIHNpemUgPSAxLjIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiT2JzZXJ2ZWQgdnMgQ29ycmVjdGVkIFByZWRpY3RlZCBUZW1wZXJhdHVyZXMgLSBZRiBSQ1AgOC41IiwKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgIGNvbG9yID0gIlRlbXBlcmF0dXJlIFR5cGUiCiAgKSArCiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIgPSAiYmx1ZSIsICJPYnNlcnZlZCIgPSAiYmxhY2siKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDg1LCBoanVzdCA9IDEpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGVkX1lGODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKUGxvdHRpbmcgdGhlIHZhbHVlcyBoZXJlCgpgYGB7cn0KIyBQbG90IE9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIChObyBPYnNlcnZlZCBWYWx1ZXMpClBsb3QgPC0gZ2dwbG90KCkgKwogICMgUGxvdCB0aGUgb3JpZ2luYWwgcHJlZGljdGVkIHRlbXBlcmF0dXJlcyAodW5jb3JyZWN0ZWQpCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl84NV90cmltbWVkLCBhZXMoeCA9IGRhdGUsIHkgPSBhdmdfdGVtcGVyYXR1cmUsIGNvbG9yID0gIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiksIHNpemUgPSAxLjIsIGxpbmV0eXBlID0gInNvbGlkIikgKwogIAogICMgUGxvdCB0aGUgY29ycmVjdGVkIHByZWRpY3RlZCB0ZW1wZXJhdHVyZXMKICBnZW9tX2xpbmUoZGF0YSA9IFlGXzg1X3RyaW1tZWQsIGFlcyh4ID0gZGF0ZSwgeSA9IGNvcnJlY3RlZF90ZW1wLCBjb2xvciA9ICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiKSwgc2l6ZSA9IDEuMiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIAogICMgU2V0IHBsb3QgbGFiZWxzCiAgbGFicygKICAgIHRpdGxlID0gIk9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIC0gWUYgUkNQIDguNSIsCiAgICB4ID0gIkRhdGUiLAogICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICBjb2xvciA9ICJUZW1wZXJhdHVyZSBUeXBlIgogICkgKwogIAogICMgQ3VzdG9taXplIHgtYXhpcyB0byBzaG93IG1vbnRocy95ZWFycyBjbGVhcmx5CiAgc2NhbGVfeF9kYXRlKAogICAgZGF0ZV9sYWJlbHMgPSAiJWIgJVkiLCAgICAjIEZvcm1hdCB4LWF4aXMgYXMgTW9udGgtWWVhcgogICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsICAjIFNldCBicmVha3MgZXZlcnkgbW9udGgKICAgIGV4cGFuZCA9IGMoMCwgMCkgICAgICAgICAgIyBSZW1vdmUgZXh0cmEgc3BhY2UgYXQgdGhlIGVkZ2VzCiAgKSArCiAgCiAgIyBEZWZpbmUgY3VzdG9tIGNvbG9ycyBmb3IgdGhlIHBsb3QKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJlZGljdGVkIChVbmNvcnJlY3RlZCkiID0gInJlZCIsICJQcmVkaWN0ZWQgKENvcnJlY3RlZCkiID0gImJsdWUiKSkgKwogIAogICMgTWluaW1hbCB0aGVtZSBmb3IgdGhlIHBsb3QKICB0aGVtZV9taW5pbWFsKCkgKwogIAogICMgQ3VzdG9taXphdGlvbnMgZm9yIGFwcGVhcmFuY2UKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gODUsIGhqdXN0ID0gMSksICAjIFJvdGF0ZSB4LWF4aXMgbGFiZWxzIGZvciBjbGFyaXR5CiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKQogICkKUGxvdAoKZ2dzYXZlKCJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vUGxvdHMvQ29ycmVjdGVkQ29tcGFyaXNvbl9ZRjg1LmpwZWciLCBwbG90ID0gUGxvdCwgd2lkdGggPSA4LCBoZWlnaHQgPSA2KQoKYGBgCkNvcnJlY3Rpb24gYXBwbGllZCB0byB0aGUgd2hvbGUgZGF0YXNldAoKYGBge3J9CiMgQXBwbHkgdGhlIHotc2NvcmUgYmlhcyBjb3JyZWN0aW9uIHRvIHRoZSBwcmVkaWN0ZWQgZGF0YQpZRl84NSRjb3JyZWN0ZWRfdGVtcCA8LSAoWUZfODUkYXZnX3RlbXBlcmF0dXJlIC0gbXVfcHJlZCkgLyBzaWdtYV9wcmVkICogc2lnbWFfb2JzICsgbXVfb2JzCgojIENoZWNrIHRoZSBmaXJzdCBmZXcgcm93cyB0byB2ZXJpZnkKaGVhZChZRl84NSkKYGBgCgpQbG90IHRoaXMgdG8gbWFrZSBpdCBpbnRvIHRoZSBzYW1lIHByZWRpY3RlZCAoY29ycmVjdGVkKSArIHByZWRpY3RlZCAodW5jb3JyZWN0ZWQpIHdpdGggdGhlIGVycm9yIGluY2x1ZGVkCgpgYGB7cn0KIyBQbG90IE9yaWdpbmFsIHZzIENvcnJlY3RlZCBQcmVkaWN0ZWQgVGVtcGVyYXR1cmVzIChObyBPYnNlcnZlZCBWYWx1ZXMpClBsb3QgPC0gZ2dwbG90KCkgKwogICMgUGxvdCB0aGUgb3JpZ2luYWwgcHJlZGljdGVkIHRlbXBlcmF0dXJlcyAodW5jb3JyZWN0ZWQpCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl84NSwgYWVzKHggPSBkYXRlLCB5ID0gYXZnX3RlbXBlcmF0dXJlLCBjb2xvciA9ICJQcmVkaWN0ZWQgKFVuY29ycmVjdGVkKSIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJzb2xpZCIpICsKICAKICAjIFBsb3QgdGhlIGNvcnJlY3RlZCBwcmVkaWN0ZWQgdGVtcGVyYXR1cmVzCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl84NSwgYWVzKHggPSBkYXRlLCB5ID0gY29ycmVjdGVkX3RlbXAsIGNvbG9yID0gIlByZWRpY3RlZCAoQ29ycmVjdGVkKSIpLCBzaXplID0gMS4yLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgCiAgZ2VvbV9saW5lKGRhdGEgPSBZRl9haXJwb3J0LCBhZXMoeCA9IERhdGUsIHkgPSBBaXJfTW9udGhBdmcsIGNvbG9yID0gIk9ic2VydmVkIiksIHNpemUgPSAxLjIpICsKICAKICAjIFNldCBwbG90IGxhYmVscwogIGxhYnMoCiAgICB0aXRsZSA9ICJPcmlnaW5hbCB2cyBDb3JyZWN0ZWQgUHJlZGljdGVkIFRlbXBlcmF0dXJlcyAtIFlGIFJDUCA4LjUiLAogICAgeCA9ICJEYXRlIiwKICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAogICAgY29sb3IgPSAiVGVtcGVyYXR1cmUgVHlwZSIKICApICsKICAKICAjIEN1c3RvbWl6ZSB4LWF4aXMgdG8gc2hvdyBtb250aHMveWVhcnMgY2xlYXJseQogIHNjYWxlX3hfZGF0ZSgKICAgIGRhdGVfbGFiZWxzID0gIiViICVZIiwgICAgIyBGb3JtYXQgeC1heGlzIGFzIE1vbnRoLVllYXIKICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLCAgIyBTZXQgYnJlYWtzIGV2ZXJ5IG1vbnRoCiAgICBleHBhbmQgPSBjKDAsIDApICAgICAgICAgICMgUmVtb3ZlIGV4dHJhIHNwYWNlIGF0IHRoZSBlZGdlcwogICkgKwogIAogICMgRGVmaW5lIGN1c3RvbSBjb2xvcnMgZm9yIHRoZSBwbG90CiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlByZWRpY3RlZCAoVW5jb3JyZWN0ZWQpIiA9ICJyZWQiLCAiUHJlZGljdGVkIChDb3JyZWN0ZWQpIiA9ICJibHVlIikpICsKICAKICAjIE1pbmltYWwgdGhlbWUgZm9yIHRoZSBwbG90CiAgdGhlbWVfbWluaW1hbCgpICsKICAKICAjIEN1c3RvbWl6YXRpb25zIGZvciBhcHBlYXJhbmNlCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDg1LCBoanVzdCA9IDEpLCAgIyBSb3RhdGUgeC1heGlzIGxhYmVscyBmb3IgY2xhcml0eQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkKICApClBsb3QKCmdnc2F2ZSgiQmlhc0NvcnJlY3Rpb24vR2VvX0JpYXNDb3JyZWN0aW9uL1Bsb3RzL0Z1bGxDb3JyZWN0aW9uX1lGODUuanBlZyIsIHBsb3QgPSBQbG90LCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCmBgYAoKClNhdmUgdGhlIG5ldyBmaWxlCgpgYGB7cn0KIyBTYXZlIHRoZSB1cGRhdGVkIGRhdGFzZXQgd2l0aCB0aGUgY29ycmVjdGVkIHRlbXBlcmF0dXJlcyB0byBhIG5ldyBDU1YgZmlsZQp3cml0ZS5jc3YoWUZfODUsICJCaWFzQ29ycmVjdGlvbi9HZW9fQmlhc0NvcnJlY3Rpb24vRGF0YUZpbGVzL1NOQVBfWUY4NV9jb3JyZWN0ZWQuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCg==